package com.zg.job.batch.four;

import com.zg.job.batch.User;
import com.zg.job.config.CustomJobExecutionListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.*;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * <p>Description: </p>
 *
 * @author zhanfeng.liang
 * @since 2025/3/3 11:52
 */
@Component
@Slf4j
public class FourJobDo {

    @Resource
    private JobBuilderFactory jobBuilderFactory;

    @Resource
    private StepBuilderFactory stepBuilderFactory;

    @Autowired
    private CustomJobExecutionListener customJobExecutionListener;

    @Autowired
    private DataSource dataSource;

    @Bean(name = "fourJob")
    public Job fourJob() {
        return jobBuilderFactory.get("fourJob")
                .start(step())
                .listener(customJobExecutionListener)
                .build();
    }

    //@Bean(name="userStep")
    public Step step() {
        return stepBuilderFactory.get("userStep")
                    .<User, User>chunk(100) // 每处理100条提交一次事务
                .reader(reader())
                .processor(processor())
                .writer(writer())
                .faultTolerant()
                .skipLimit(10)              // 允许跳过的最大错误数
                .skip(DataIntegrityViolationException.class)
                .retryLimit(0) // 禁止重试）
                //.noSkip(DataIntegrityViolationException.class) // 禁止跳过的异常
                .listener(new StepListener())
                .build();
    }

    //@Bean(name = "userReader")
    public FlatFileItemReader<User> reader() {
        return new FlatFileItemReaderBuilder<User>()
                .name("userItemReader")
                .resource(new ClassPathResource("user.csv"))
                .encoding("GBK")
                .delimited()
                .names("id", "name", "email") // CSV 列名
                .targetType(User.class) // 映射到数据模型
                .build();
    }

    //@Bean(name = "userProcessor")
    public ItemProcessor<User, User> processor() {
        return user -> {
            // 示例：将名称转为大写
            user.setName(user.getName().toUpperCase());
            return user;
        };
    }

    //@Bean(name = "userWriter")
    public JdbcBatchItemWriter<User> writer() {
        //DataSource dataSource = SpringUtil.getBean(DataSource.class);
        JdbcBatchItemWriter jdbcBatchItemWriter = new JdbcBatchItemWriterBuilder<User>()
                .dataSource(dataSource)
                .sql("INSERT INTO user (id, name, email) VALUES (:id,:name,:email)")
                .beanMapped() // 关键配置：自动映射属性到命名参数
                .build();
        jdbcBatchItemWriter.afterPropertiesSet();
        return  jdbcBatchItemWriter;
    }

    public class StepListener implements StepExecutionListener {
        @Override
        public void beforeStep(StepExecution stepExecution) {
            log.info(stepExecution.getStepName()+"开始: " + stepExecution.getStepName());
        }

        @Override
        public ExitStatus afterStep(StepExecution stepExecution) {
            if (stepExecution.getStatus().isUnsuccessful()) {
                // 打印错误信息
                log.error("Step 执行失败: " + stepExecution.getStepName());
                log.error("失败原因: " + stepExecution.getFailureExceptions());
            }else {
                log.info("Step处理数量: " + stepExecution.getReadCount());
                log.info("Step跳过数量: " + stepExecution.getSkipCount());
            }

            return stepExecution.getExitStatus();
        }
    }

    public JdbcBatchItemWriter<User> userWriter(DataSource dataSource) {
        return new JdbcBatchItemWriterBuilder<User>()
                .dataSource(dataSource)
                .sql("INSERT INTO users (id, name, email) VALUES (:id, :name, :email)")
                .beanMapped() // 自动映射属性到命名参数
                .build();
    }

}
